package com.youlai.boot.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.common.exception.BusinessException;
import com.youlai.boot.core.security.util.SecurityUtils;
import com.youlai.boot.system.enums.RecycleStatusEnum;
import com.youlai.boot.system.mapper.*;
import com.youlai.boot.system.model.dto.EmissionReductionDTO;
import com.youlai.boot.system.model.entity.*;
import com.youlai.boot.system.model.form.RecycleRequestForm;
import com.youlai.boot.system.model.query.RecycleRequestQuery;
import com.youlai.boot.system.model.vo.RecycleRequestVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.boot.system.service.RecycleRequestService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 回收请求主服务实现类
 *
 * @author youlaitech
 * @since 2025-02-23 21:14
 */
@Service
@RequiredArgsConstructor
public class RecycleRequestServiceImpl extends ServiceImpl<RecycleRequestMapper, RecycleRequest> implements RecycleRequestService {

    // 主表
    private final RecycleRequestMapper recycleRequestMapper;
    // 关联表
    private final RequestWasteMapper requestWasteMapper;
    // 垃圾类型表
    private final WasteTypeMapper wasteTypeMapper;

    private final TaskAssignmentMapper taskAssignmentMapper;

    /**
     * 用户发请回收请求
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean initUserRecycleRequest(RecycleRequestForm dto) {
        Long userId = SecurityUtils.getUserId();
        // 1.生成回收任务主表，待审核状态
        RecycleRequest recycleRequest = RecycleRequest.builder()
                .userId(userId)
                .province(dto.getArea().get(0))
                .city(dto.getArea().get(1))
                .country(dto.getArea().get(2))
                .address(dto.getAddress())
                .recycleTime(dto.getRecycleTime())
                .mobile(dto.getMobile())
                .expectReturn(dto.getExpectReturn())
                .remark(dto.getRemark())
                .status(RecycleStatusEnum.PENDING_REVIEW.getCode())
                .build();
        recycleRequestMapper.insert(recycleRequest);
        return true;
    }

    /**
     * 所有垃圾类别
     * @return
     */
    @Override
    public List<WasteType> getAllWasteType() {
        List<WasteType> wasteTypes = wasteTypeMapper.selectList(null);
        if (wasteTypes != null) {
            return wasteTypes;
        }
        return List.of();
    }

    /**
     * 回写表单数据
     * @param id
     * @return
     */
    @Override
    public RecycleRequestForm getRecycleRequestFormData(Long id) {
        RecycleRequestForm form = new RecycleRequestForm();
        RecycleRequest recycleRequest = recycleRequestMapper.selectById(id);
        BeanUtil.copyProperties(recycleRequest, form);
        form.setArea(List.of(recycleRequest.getProvince(), recycleRequest.getCity(), recycleRequest.getCountry()));
        form.setWasteList(new LambdaQueryChainWrapper<>(requestWasteMapper).eq(RequestWaste::getRequestId, id).list());
        return form;
    }

    @Override
    public LinkedHashMap<String, List<RecycleRequestVO>> getPage(RecycleRequestQuery queryParams) {
        Long userId = SecurityUtils.getUserId();
        // 按创建时间进行分类
        LinkedHashMap<String, List<RecycleRequestVO>> resultMap = new LinkedHashMap<>();
        LambdaQueryWrapper<RecycleRequest> queryWrapper = new LambdaQueryWrapper<>();
        // 查询的用户
        queryWrapper.eq(RecycleRequest::getUserId, userId);
        // 主表状态
        List<RecycleRequest> recycleRequests = conditionalQuery(queryParams, queryWrapper);

        // 按创建时间分组
        if (CollUtil.isNotEmpty(recycleRequests)) {
            // 批量查询 requestWaste 数据
            List<Long> requestIds = recycleRequests.stream()
                    .map(RecycleRequest::getId)
                    .filter(Objects::nonNull)
                    .toList();
            Map<Long, List<RequestWaste>> wasteMap = new LambdaQueryChainWrapper<>(requestWasteMapper)
                    .in(RequestWaste::getRequestId, requestIds)
                    .list()
                    .stream()
                    .collect(Collectors.groupingBy(RequestWaste::getRequestId));

            // 按创建时间倒序排序并分组
            LinkedHashMap<String, List<RecycleRequestVO>> tempMap = recycleRequests.stream()
                    .filter(Objects::nonNull) // 过滤掉空值
                    .map(item -> {
                        RecycleRequestVO vo = new RecycleRequestVO();
                        BeanUtil.copyProperties(item, vo);
                        vo.setArea(List.of(item.getProvince(), item.getCity(), item.getCountry()));
                        vo.setWasteList(wasteMap.getOrDefault(item.getId(), Collections.emptyList()));
                        try {
                            vo.setCreateTime(item.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                        } catch (Exception e) {
                            // 捕获日期格式化异常，设置默认值或记录日志
                            vo.setCreateTime("未知日期");
                        }
                        return vo;
                    })
                    .collect(Collectors.groupingBy(
                            RecycleRequestVO::getCreateTime,
                            LinkedHashMap::new, // 使用 LinkedHashMap 保持插入顺序
                            Collectors.toList()
                    ));

            // 对 map 的 key 进行倒序排序
            List<Map.Entry<String, List<RecycleRequestVO>>> sortedEntries = tempMap.entrySet().stream()
                    .sorted((e1, e2) -> {
                        try {
                            LocalDate date1 = LocalDate.parse(e1.getKey(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                            LocalDate date2 = LocalDate.parse(e2.getKey(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                            return date2.compareTo(date1);
                        } catch (Exception e) {
                            // 捕获日期解析异常，保持原顺序
                            return 0;
                        }
                    })
                    .toList();

            // 构造最终结果 map
            LinkedHashMap<String, List<RecycleRequestVO>> finalMap = new LinkedHashMap<>();
            sortedEntries.forEach(entry -> finalMap.put(entry.getKey(), entry.getValue()));
            return finalMap;
        }
        return resultMap;
    }


    private List<RecycleRequest> conditionalQuery(RecycleRequestQuery queryParams, LambdaQueryWrapper<RecycleRequest> queryWrapper) {
        if (queryParams.getStatus() != null) {
            queryWrapper.eq(RecycleRequest::getStatus, queryParams.getStatus());
        }
        // 主表创建时间
        if (queryParams.getCreateTimeStart() != null) {
            queryWrapper.ge(RecycleRequest::getCreateTime, queryParams.getCreateTimeStart());
        }
        if (queryParams.getCreateTimeEnd() != null) {
            queryWrapper.le(RecycleRequest::getCreateTime, queryParams.getCreateTimeEnd());
        }
        // 主表期望收益
        if (queryParams.getMinExpectReturn() != null) {
            queryWrapper.ge(RecycleRequest::getExpectReturn, queryParams.getMinExpectReturn());
        }
        if (queryParams.getMaxExpectReturn() != null) {
            queryWrapper.le(RecycleRequest::getExpectReturn, queryParams.getMaxExpectReturn());
        }
        // TODO 不分页查询，查询所有
        List<RecycleRequest> recycleRequests = recycleRequestMapper.selectList(queryWrapper);
        return recycleRequests;
    }

    /**
     * 用户修改申请请求
     * @param form
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUserRecycleRequest(RecycleRequestForm form) {
        // 1.修改主表信息
        RecycleRequest entity = new RecycleRequest();
        BeanUtil.copyProperties(form, entity);
        if (form.getArea() != null) {
            entity.setProvince(form.getArea().get(0));
            entity.setCity(form.getArea().get(1));
            entity.setCountry(form.getArea().get(2));
        }
        // 修改状态，如果是驳回，需额外操作
        if (entity.getStatus().equals(RecycleStatusEnum.REJECTED.getCode())) {
            // 删除配送表中该申请任务
            taskAssignmentMapper.delete(new LambdaQueryWrapper<TaskAssignment>().eq(TaskAssignment::getRequestId, entity.getId()));
            // 为方便，直接在原表上修改
            entity.setStatus(RecycleStatusEnum.PENDING_REVIEW.getCode());
            entity.setRejectReason("");
        } else if (entity.getStatus().equals(RecycleStatusEnum.ROLL_BACKING.getCode())) {
            entity.setStatus(RecycleStatusEnum.ROLL_BACKED.getCode());
        }

        entity.setUpdateTime(LocalDateTime.now());
        recycleRequestMapper.updateById(entity);

        // 2.修改关联垃圾表,先删除后新增
        requestWasteMapper.delete(new LambdaQueryWrapper<RequestWaste>().eq(RequestWaste::getRequestId, entity.getId()));
        form.getWasteList().forEach(rw -> {
            RequestWaste requestWaste = RequestWaste.builder()
                    .requestId(entity.getId())
                    .fileUrl(rw.getFileUrl())
                    .typeId(rw.getTypeId())
                    .weight(rw.getWeight())
                    .actualPrice(rw.getActualPrice())
                    .build();
            requestWasteMapper.insert(requestWaste);
        });

        return true;
    }

    @Override
    public Boolean applyCancelRequest(RecycleRequestForm recycleRequestForm) {
        Long requestId = recycleRequestForm.getId();
        RecycleRequest recycleRequest = recycleRequestMapper.selectById(requestId);
        recycleRequest.setStatus(RecycleStatusEnum.CANCELING.getCode());
        recycleRequest.setCancelReason(recycleRequestForm.getCancelReason());
        recycleRequestMapper.updateById(recycleRequest);
        return true;
    }

    /**
     * 首页统计Echarts 碳减排量/率
     * @param periodType 周期类型：
     *      0: 30天 （一个月） 单位：天 01-12
     *      1:180天 （六个月） 单位：月 2024-01
     * @return
     */
    @Override
    public List<EmissionReductionDTO> calculateReductions(Integer periodType) {
        // 定义日期格式化器
        final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        final DateTimeFormatter MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM");

        // 参数校验，确保周期类型正确
        if (periodType == null || (periodType != 0 && periodType != 1)) {
            throw new BusinessException("未知的统计日期范围类型");
        }

        // 初始化DTO列表
        List<EmissionReductionDTO> dtoList = new ArrayList<>();
        // 获取废弃物类型映射
        Map<Long, WasteType> wasteTypeMap = wasteTypeMapper.selectList(null)
                .stream()
                .collect(Collectors.toMap(WasteType::getId, Function.identity()));

        // 确定起止日期及其格式
        LocalDate endDate = LocalDate.now();
        LocalDate startDate;
        DateTimeFormatter groupFormatter;

        if (periodType == 0) {
            startDate = endDate.minusDays(30);
            groupFormatter = DATE_FORMATTER;
        } else {
            startDate = endDate.minusMonths(6).withDayOfMonth(1);
            endDate = endDate.with(TemporalAdjusters.lastDayOfMonth());
            groupFormatter = MONTH_FORMATTER;
        }

        // 格式化起止日期字符串
        String startStr = startDate.format(DATE_FORMATTER);
        String endStr = endDate.format(DATE_FORMATTER);

        // 查询所有已完成的回收请求
        List<RecycleRequest> finishRequests = recycleRequestMapper.selectList(new LambdaQueryWrapper<RecycleRequest>()
                .between(RecycleRequest::getCreateTime, startStr, endStr)
                .eq(RecycleRequest::getStatus, RecycleStatusEnum.RECYCLED.getCode()));

        // 批量获取所有请求的废弃物数据
        Set<Long> requestIds = finishRequests.stream().map(RecycleRequest::getId).collect(Collectors.toSet());
        if (requestIds.isEmpty()) {
            return dtoList;
        }
        Map<Long, List<RequestWaste>> wastesMap = requestWasteMapper.selectList(
                new LambdaQueryWrapper<RequestWaste>().in(RequestWaste::getRequestId, requestIds)
        ).stream().collect(Collectors.groupingBy(RequestWaste::getRequestId));

        // 使用TreeMap自动按日期字符串排序
        TreeMap<String, BigDecimal> emissionMap = finishRequests.stream()
                .collect(Collectors.groupingBy(
                        request -> request.getCreateTime().format(groupFormatter),
                        TreeMap::new,  // 关键修改：使用有序Map
                        Collectors.mapping(
                                Function.identity(),
                                Collectors.collectingAndThen(
                                        Collectors.toList(),
                                        reqList -> reqList.stream()
                                                .flatMap(req -> wastesMap.getOrDefault(req.getId(), Collections.emptyList()).stream())
                                                .map(waste -> {
                                                    WasteType type = wasteTypeMap.get(waste.getTypeId());
                                                    BigDecimal weightKg = waste.getWeight().multiply(new BigDecimal("0.001"));
                                                    return type.getCerc().multiply(weightKg);
                                                })
                                                .reduce(BigDecimal.ZERO, BigDecimal::add)
                                )
                        )
                ));

        // 初始化前一个周期的碳减排量
        BigDecimal previousReduction = null;

        // 遍历每个周期的碳减排量，计算减排率
        for (Map.Entry<String, BigDecimal> entry : emissionMap.entrySet()) {
            EmissionReductionDTO dto = new EmissionReductionDTO();
            dto.setPeriod(entry.getKey());
            BigDecimal currentReduction = entry.getValue();
            dto.setReduction(currentReduction);

            // 计算碳减排率
            if (previousReduction != null && previousReduction.compareTo(BigDecimal.ZERO) != 0) {
                BigDecimal rate = currentReduction
                        .divide(previousReduction, 4, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("100"))
                        .setScale(2, RoundingMode.HALF_UP);
                dto.setReductionRate(rate);
            } else {
                dto.setReductionRate(BigDecimal.ZERO); // 首条数据或前序为0时设为0%
            }

            // 添加到DTO列表
            dtoList.add(dto);
            // 更新前一个周期的碳减排量
            previousReduction = currentReduction;
        }

        // 返回碳减排DTO列表
        return dtoList;
    }


}
